package com.qiqi.ctbluetooth

import android.Manifest
import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Color
import android.graphics.PorterDuff
import android.media.MediaCodec
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.Settings
import android.util.Log
import android.view.Gravity
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.activity.OnBackPressedCallback
import androidx.activity.viewModels
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageCapture
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import cn.wandersnail.bluetooth.EventObserver
import cn.wandersnail.commons.util.StringUtils
import com.blankj.utilcode.util.FileUtils
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.SizeUtils
import com.blankj.utilcode.util.TimeUtils
import com.blankj.utilcode.util.ToastUtils
import com.clj.fastble.data.BleDevice
import com.clj.fastble.utils.HexUtil
import com.drake.brv.utils.linear
import com.drake.brv.utils.setup
import com.drake.engine.base.EngineActivity
import com.drake.interval.Interval
import com.dylanc.longan.getCompatColor
import com.dylanc.longan.safeIntentExtras
import com.dylanc.longan.startActivity
import com.dylanc.longan.toast
import com.github.gzuliyujiang.filepicker.ExplorerConfig
import com.github.gzuliyujiang.filepicker.FilePicker
import com.github.gzuliyujiang.filepicker.annotation.ExplorerMode
import com.github.mikephil.charting.data.Entry
import com.gyf.immersionbar.BarHide
import com.gyf.immersionbar.ImmersionBar
import com.hjq.permissions.OnPermissionCallback
import com.hjq.permissions.XXPermissions
import com.hjq.permissions.permission.PermissionLists
import com.hjq.permissions.permission.base.IPermission
import com.hjq.shape.view.ShapeButton
import com.hjq.shape.view.ShapeImageView
import com.kongzue.dialogx.dialogs.CustomDialog
import com.kongzue.dialogx.dialogs.MessageDialog
import com.kongzue.dialogx.dialogs.PopMenu
import com.kongzue.dialogx.dialogs.TipDialog
import com.kongzue.dialogx.dialogs.WaitDialog
import com.kongzue.dialogx.interfaces.DialogLifecycleCallback
import com.kongzue.dialogx.interfaces.OnBindingView
import com.qiqi.ctbluetooth.UserDataLocal.currentChannel
import com.qiqi.ctbluetooth.data.ColorData
import com.qiqi.ctbluetooth.data.DacPointData
import com.qiqi.ctbluetooth.databinding.ActivityChartBinding
import com.qiqi.ctbluetooth.databinding.DialogColorBinding
import com.qiqi.ctbluetooth.databinding.DialogFileExplorerBinding
import com.qiqi.ctbluetooth.databinding.DialogPararmBinding
import com.qiqi.ctbluetooth.databinding.DialogSettingBinding
import com.qiqi.ctbluetooth.databinding.DialogSettingItemBinding
import com.qiqi.ctbluetooth.permission.PermissionDescription
import com.qiqi.ctbluetooth.permission.PermissionInterceptor
import com.qiqi.ctbluetooth.permission.requestCameraPermissions
import com.qiqi.ctbluetooth.util.CameraLifecycle
import com.qiqi.ctbluetooth.util.LineChartManager
import com.qiqi.ctbluetooth.util.Utils
import io.keyss.view_record.RecordEncoder
import io.keyss.view_record.recording.RecordController
import io.keyss.view_record.recording.ViewRecorder
import io.keyss.view_record.video.EncoderErrorCallback
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import java.io.File
import java.math.BigDecimal
import java.math.RoundingMode
import java.util.concurrent.TimeUnit


class ChartActivity : EngineActivity<ActivityChartBinding>(R.layout.activity_chart), EventObserver{
    companion object{
        const val WIDTH = 25
        const val MAX_X = 499
        fun lunch(device: BleDevice) = startActivity<ChartActivity>("device" to device)
    }

    val blueViewModel: BlueViewModel by viewModels()

    //相机参数
    private var isOpenCamera = false
    private var isOpenSave = false
    private var isOpenBaoluo = false
    //是否暂停启动
    private var isPause = false
    private var mTimerJob: Job? = null
    private var mStartTime = 0L
    private val mRecordEncoder = RecordEncoder()
    private val viewRecord = ViewRecorder()
    private var mLastRecordFile: File? = null

    private lateinit var cameraLifecycle: CameraLifecycle
    private lateinit var imageCapture: ImageCapture
    private var lastStreamState: PreviewView.StreamState? = null

    //创建一个512位的ByteArray
    private var baolupArray = FloatArray(500) { 0f }

    private var dacPointList  = mutableListOf<DacPointData>()
    private var job: Job? = null // 用于管理协程任务
    private var delayJob: Job? = null
    private var isLoadGuile = true
    private var isManualDisconnect = false


    private val device: BleDevice by safeIntentExtras("device")


    override fun initData() {
        blueViewModel.connectBleDevice(device)
        blueViewModel.onConnectFailed = { device, exception ->
            TipDialog.show("连接失败", WaitDialog.TYPE.ERROR);
            finish()
        }
        blueViewModel.onConnectSuccess = { device ->
            TipDialog.show("连接成功", WaitDialog.TYPE.SUCCESS);
         }
        blueViewModel.onDisconnected = { device ->
            if (isManualDisconnect) {
                TipDialog.show("已断开连接", WaitDialog.TYPE.ERROR)
                finish()
            }else{
                TipDialog.show("尝试重新连接", WaitDialog.TYPE.WARNING)
                blueViewModel.connectBleDevice(device)
            }


        }
        blueViewModel.onCompleteData = { data ->
//            LogUtils.iTag("onCompleteData", "Notify接收到数据==>" + HexUtil.formatHexString(data,true))
            if (!isPause){
                requireActivity().runOnUiThread { updateChart(data) }
            }
        }
    }

    @SuppressLint("MissingPermission", "ClickableViewAccessibility")
    override fun initView() {
        ImmersionBar.with(this).hideBar(BarHide.FLAG_HIDE_BAR).init()
        binding.v = this

        onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                MessageDialog.show("提示","是否退出？", "确定","取消")
                    .setOkButton { dialog, text ->
                        isManualDisconnect = true
                        finishTransition()
                        false
                    }.setCancelButton { dialog, text ->
                        isManualDisconnect = false
                        false
                    }
            }
        })


        LogUtils.e("UserDataLocalsendData",UserDataLocal.sendData)
        updateBgColor()
        //从本地取出上次保存的步进值
        var list = Utils.getSteppingData()
        var index = list.indexOf(UserDataLocal.stepping)
        var channelList = UserDataLocal.getChannelList()
        val channelData = channelList[currentChannel]
        binding.tvStepping.text = list[if (index == -1) 0 else index].toString()

        binding.tvMode.text = if (UserDataLocal.isDoubleChannel()) "单" else "双"
        binding.tvBuff.text = Utils.getBuffStr()
        binding.tvBuff2.text = Utils.getBuffStr()

        binding.tvAngle.text = "角度: K${BigDecimal(channelData.kValue).setScale(2, RoundingMode.HALF_UP)}"
        binding.tvAngle2.text = "角度: K${BigDecimal(channelData.kValue).setScale(2, RoundingMode.HALF_UP)}"
        binding.tvLc.text = "测距: ${channelData.lcList[channelData.selectLcIndex].name}"
        binding.tvLc2.text = "测距: ${channelData.lcList[channelData.selectLcIndex].name}"
        binding.tvInhibition.text = "抑制: ${ Utils.toZero(UserDataLocal.globalInhibition)}%"
        binding.tvInhibition2.text = "抑制: ${ Utils.toZero(UserDataLocal.globalInhibition)}%"
        binding.btnChannel.text = channelData.name
        binding.btnChannel2.text = channelData.name


        LineChartManager.initChart(binding.chartView)
        LineChartManager.setGuidelines(binding.chartView)

        cameraLifecycle = CameraLifecycle()
        cameraLifecycle.cameraOnCreate()
        //监听PreviewView的画面输出状态
        binding.cameraView.previewStreamState.observe(this) { streamState ->
            Log.i("CameraTest", "previewStreamState :${streamState.name} ,lastStreamState:$lastStreamState")
            if (lastStreamState == null) {
                lastStreamState = streamState
            } else {
                when (streamState) {
                    //输出画面
                    PreviewView.StreamState.STREAMING -> {
                        if (lastStreamState != streamState) {
                            lastStreamState = streamState

                            //开始输出画面后清空前景
                            binding.cameraView.foreground = null
                        }
                    }
                    //停止输出画面
                    PreviewView.StreamState.IDLE -> {
                        if (lastStreamState != streamState) {
                            lastStreamState = streamState
                            //停止输出画面后仍会停留在最后一帧，设置黑色前景遮挡最后一帧画面
                            binding.cameraView.foreground = ContextCompat.getDrawable(this, android.R.color.background_dark)
                        }
                    }
                    else -> {}
                }
            }
        }

        Interval(1, TimeUnit.SECONDS).subscribe {
            binding.tvDate.text = TimeUtils.getNowString()
        }.life(this).onlyResumed(this).start()

        // 设置每个按钮的长按监听
        setLongPressListener(binding.btnAddBuff, (UserDataLocal.stepping * 10).toInt())
        setLongPressListener(binding.btnAddBuff2, (UserDataLocal.stepping * 10).toInt())
        setLongPressListener(binding.btnReduceBuff, -(UserDataLocal.stepping * 10).toInt())
        setLongPressListener(binding.btnReduceBuff2, -(UserDataLocal.stepping * 10).toInt())
        setChartPadding()

        //默认开启DAC
        dacPointList = UserDataLocal.getChannelList()[currentChannel].dacPointList
        for (point in dacPointList){
            var newY = point.y * Math.pow(10.0, ((UserDataLocal.globalBuff - point.db).toDouble()/200))
            point.db = UserDataLocal.globalBuff
            point.y = newY.toFloat()
        }
        LineChartManager.updateDacLine(binding.chartView,dacPointList)
    }

    // 按钮点击监听设置的优化
    private fun setLongPressListener(button: View, buff: Int) {
        button.setOnTouchListener { _, event ->
            when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    // 当按钮按下时，启动协程
                    startDelayedLongPressTask(buff)
                    false
                }
                MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                    // 当按钮抬起或触摸取消时，停止协程
                    stopLongPressTask()
                    false
                }
                else -> false
            }
        }
    }

    // 启动一个延迟协程，在1秒后启动长按任务
    private fun startDelayedLongPressTask(buff: Int) {
        delayJob?.cancel()
        delayJob = lifecycleScope.launch {
            delay(1000) // 延迟1秒
            startLongPressTask(buff)
        }
    }


    // 启动一个协程，每隔500ms调用一次方法
    private fun startLongPressTask(buff: Int) {
        // 如果当前已有协程，先取消掉
        job?.cancel()
        job = lifecycleScope.launch {
            while (true) {
                updateBuff(buff)
                delay(50) // 每隔50ms调用一次
            }
        }
    }

    // 停止协程任务
    private fun stopLongPressTask() {
        delayJob?.cancel() // 取消协程任务
        job?.cancel() // 取消协程任务
    }




    fun setChartPadding(){
        val marginBottom = SizeUtils.dp2px(if (isOpenCamera) 10f else 3f).toInt()
        val marginTop = SizeUtils.dp2px(if (isOpenCamera) -25f else -25f).toInt()
        val layoutParams = binding.chartView.layoutParams as ViewGroup.MarginLayoutParams
        layoutParams.bottomMargin = marginBottom
        layoutParams.topMargin = marginTop
        binding.chartView.layoutParams = layoutParams
    }

    override fun onClick(v: View) {
        super.onClick(v)
        when(v.id){
            R.id.imgCamera ->{ //打开摄像头
                XXPermissions.with(this)
                    .permission(PermissionLists.getCameraPermission())
                    .interceptor(PermissionInterceptor())
                    .description(PermissionDescription())
                    .request(object : OnPermissionCallback {
                        override fun onResult(grantedList: List<IPermission?>, deniedList: List<IPermission?>) {
                            var allGranted = deniedList.isEmpty();
                            if (!allGranted) {
                                ToastUtils.showShort("摄像头权限获取失败==》$deniedList")
                                binding.imgCamera.setImageResource(R.mipmap.ic_camera_error)
                                return;
                            }
                            bindCamera()
                            isOpenCamera = !isOpenCamera
                            updateCameraModel(isOpenCamera)
                            binding.tvTime.visibility = if (isOpenSave && isOpenCamera) View.VISIBLE else View.GONE
                            binding.tvTime2.visibility = if (isOpenSave && !isOpenCamera) View.VISIBLE else View.GONE
                            setChartPadding()
                        }
                    })
            }
            R.id.btnBack2 ->{ //打开摄像头
                isOpenCamera = false
                updateCameraModel(false)
            }
            R.id.imgSave ->{ //开始录制
                XXPermissions.with(this)
                    .permission(PermissionLists.getCameraPermission())
                    .interceptor(PermissionInterceptor())
                    .description(PermissionDescription())
                    .request(object : OnPermissionCallback {
                        override fun onResult(grantedList: List<IPermission?>, deniedList: List<IPermission?>) {
                            var allGranted = deniedList.isEmpty();
                            if (!allGranted) {
                                ToastUtils.showShort("存储权限获取失败==》$deniedList")
                                binding.imgSave.setImageResource(R.mipmap.ic_save_red)
                                return;
                            }
                            isOpenSave = !isOpenSave
                            updateScreenRecordingModel(isOpenSave)
                        }
                    })
            }
            R.id.imgBaoLuo ->{ //包络
                isOpenBaoluo = !isOpenBaoluo
                if (isOpenBaoluo){
                    baolupArray = FloatArray(500) { 0f }
                }
                if (UserDataLocal.colorBg == Color.WHITE){
                    binding.imgBaoLuo.setImageResource(if(isOpenBaoluo) R.mipmap.ic_baoluo_black else R.mipmap.ic_baoluo_black_error)
                }else if (UserDataLocal.colorBg == Color.BLACK){
                    binding.imgBaoLuo.setImageResource(if(isOpenBaoluo) R.mipmap.ic_baoluo_white else R.mipmap.ic_baoluo_white_error)
                }
            }
            R.id.imgDac ->{ //dac 模式


                UserDataLocal.isOpenDAC = ! UserDataLocal.isOpenDAC
                if ( UserDataLocal.isOpenDAC){
                    toast( "已开启DAC模式")
                    LineChartManager.updateDataColor(this@ChartActivity.binding.chartView, LineChartManager.DAC, Utils.getFanValue(UserDataLocal.dacBg))
                    updateBuff(0)
                }else{
                    toast( "已关闭DAC模式")
                    if (UserDataLocal.colorBg == Color.WHITE){
                        LineChartManager.updateDataColor(this@ChartActivity.binding.chartView, LineChartManager.DAC, Color.WHITE)
                    }else if (UserDataLocal.colorBg == Color.BLACK){
                        LineChartManager.updateDataColor(this@ChartActivity.binding.chartView, LineChartManager.DAC, Color.BLACK)
                    }
                }

                if (UserDataLocal.colorBg == Color.WHITE){
                    binding.imgDac.setImageResource(if( UserDataLocal.isOpenDAC) R.mipmap.ic_dac_black else R.mipmap.ic_dac_black_error)
                }else if (UserDataLocal.colorBg == Color.BLACK){
                    binding.imgDac.setImageResource(if( UserDataLocal.isOpenDAC) R.mipmap.ic_dac_white else R.mipmap.ic_dac_white_error)
                }
            }
            R.id.btnAddBuff, R.id.btnAddBuff2 ->{
                updateBuff((UserDataLocal.stepping*10).toInt())
//                connect()
            }
            R.id.btnReduceBuff, R.id.btnReduceBuff2->{
                updateBuff(-(UserDataLocal.stepping*10).toInt())
//                BTManager.getInstance().disconnectConnection(device, UUIDWrapper.useDefault())
            }
            R.id.tvMode->{
                if (UserDataLocal.isDoubleChannel()){
                    binding.tvMode.text = "双"
                    UserDataLocal.saveSendData(7, "01".toInt(16).toByte())
                }else {
                    binding.tvMode.text = "单"
                    UserDataLocal.saveSendData(7, "00".toInt(16).toByte())
                }
                blueViewModel.sendData(UserDataLocal.sendData)
            }
            R.id.layStepping->{
                var list = Utils.getSteppingData()
                var index = list.indexOf(UserDataLocal.stepping)

                var nowIndex = when (index) {
                    -1 -> 0  //没查到
                    list.size - 1 -> 0 //查到，但是是最后一个
                    else -> index + 1 //查到，并且不是最后一个
                }
                //将db增益的步进值保存在本地
                UserDataLocal.stepping = list[nowIndex]
                binding.tvStepping.text = UserDataLocal.stepping.toString()
            }
            R.id.imgXing->{
                isPause = !isPause
                toast(if(isPause) "已暂停" else "已恢复")
                if (isPause){
                    binding.imgXing.setColorFilter(Color.RED, PorterDuff.Mode.SRC_IN)
                }else{
                    if (UserDataLocal.colorBg == Color.WHITE){
                        binding.imgXing.setColorFilter(Color.BLACK, PorterDuff.Mode.SRC_IN)
                    }else if (UserDataLocal.colorBg == Color.BLACK){
                        binding.imgXing.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN)
                    }
                }
            }
            R.id.btnChannel,R.id.btnChannel2->{

                //选择通道
                showChannelMenuDialog(v)
            }
            R.id.btnParam->{
                CustomDialog.show(object : OnBindingView<CustomDialog?, DialogPararmBinding?>() {
                    override fun onBind(dialog: CustomDialog?, view: View, binding: DialogPararmBinding?) {
                        var channelList = UserDataLocal.getChannelList()
                        var channelData = channelList[currentChannel]
                        binding?.tvAngle?.text = "角度: K${BigDecimal(channelData.kValue).setScale(2, RoundingMode.HALF_UP)}"
                        binding?.tvLeading?.text = "前沿: ${BigDecimal(channelData.f).setScale(1, RoundingMode.HALF_UP)}mm"
                        binding?.tvCheju?.text = "测距: ${channelData.lcList[channelData.selectLcIndex].name}"
                        binding?.tvDelay?.text = "延时: ${channelData.lcList[channelData.selectLcIndex].delay}uS"
                        binding?.tvInhibition?.text = "抑制: ${Utils.toZero(UserDataLocal.globalInhibition)}%"
                        binding?.tvAngle?.setOnClickListener{
                            binding.tvAngle.setBackgroundColor(getCompatColor(R.color.c_f5))
                            binding.tvCheju.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvInhibition.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvLeading.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvDelay.setBackgroundColor(getCompatColor(R.color.white))
                            CustomDialog.show(object : OnBindingView<CustomDialog?, DialogSettingItemBinding?>() {
                                override fun onBind(dialog: CustomDialog?, view: View, itemPararmBinding: DialogSettingItemBinding?) {
                                    itemPararmBinding?.tvName?.text = "角度"
                                    itemPararmBinding?.imgAdd?.setOnClickListener {
                                        updateChannelAngle(0.01, binding.tvAngle)

                                    }
                                    itemPararmBinding?.imgRemove?.setOnClickListener {
                                        updateChannelAngle(-0.01, binding.tvAngle)
                                    }
                                }
                            }).setAlignBaseViewGravity(binding.tvAngle, Gravity.LEFT or Gravity.CENTER_VERTICAL)
                                .setWidth(SizeUtils.dp2px(130f))
                        }
                        binding?.tvCheju?.setOnClickListener{
                            binding.tvAngle.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvCheju.setBackgroundColor(getCompatColor(R.color.c_f5))
                            binding.tvInhibition.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvLeading.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvDelay.setBackgroundColor(getCompatColor(R.color.white))
                            CustomDialog.show(object : OnBindingView<CustomDialog?, DialogSettingItemBinding?>() {
                                override fun onBind(dialog: CustomDialog?, view: View, itemPararmBinding: DialogSettingItemBinding?) {
                                    itemPararmBinding?.tvName?.text = "测距"

                                    itemPararmBinding?.imgAdd?.setOnClickListener {
                                        if (channelData.selectLcIndex < channelData.lcList.size - 1) {
                                            channelData.selectLcIndex++
                                            channelList[currentChannel] = channelData
                                            UserDataLocal.setChannelList(channelList)
                                            binding.tvCheju.text = "测距: ${channelData.lcList[channelData.selectLcIndex].name}"
                                            updateLc()
                                        }

                                    }
                                    itemPararmBinding?.imgRemove?.setOnClickListener {
                                        if (channelData.selectLcIndex > 0) {
                                            channelData.selectLcIndex--
                                            channelList[currentChannel] = channelData
                                            UserDataLocal.setChannelList(channelList)
                                            binding.tvCheju.text = "测距: ${channelData.lcList[channelData.selectLcIndex].name}"
                                            updateLc()
                                        }

                                    }
                                }
                            }).setAlignBaseViewGravity(binding.tvCheju, Gravity.LEFT or Gravity.CENTER_VERTICAL)
                                .setWidth(SizeUtils.dp2px(130f))
                        }
                        binding?.tvInhibition?.setOnClickListener{
                            binding.tvAngle.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvCheju.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvInhibition.setBackgroundColor(getCompatColor(R.color.c_f5))
                            binding.tvLeading.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvDelay.setBackgroundColor(getCompatColor(R.color.white))
                            CustomDialog.show(object : OnBindingView<CustomDialog?, DialogSettingItemBinding?>() {
                                override fun onBind(dialog: CustomDialog?, view: View, itemPararmBinding: DialogSettingItemBinding?) {
                                    itemPararmBinding?.tvName?.text = "抑制"

                                    itemPararmBinding?.imgAdd?.setOnClickListener {
                                        if (UserDataLocal.globalInhibition < 100) {
                                            UserDataLocal.globalInhibition++
                                            binding?.tvInhibition?.text = "抑制: ${Utils.toZero(UserDataLocal.globalInhibition)}%"
                                            this@ChartActivity.binding.tvInhibition.text = "抑制: ${Utils.toZero(UserDataLocal.globalInhibition)}%"
                                        }
                                    }
                                    itemPararmBinding?.imgRemove?.setOnClickListener {
                                        if (UserDataLocal.globalInhibition >0) {
                                            UserDataLocal.globalInhibition--
                                            binding?.tvInhibition?.text = "抑制: ${Utils.toZero(UserDataLocal.globalInhibition)}%"
                                            this@ChartActivity.binding.tvInhibition.text = "抑制: ${Utils.toZero(UserDataLocal.globalInhibition)}%"
                                        }

                                    }
                                }
                            })
                                .setAlignBaseViewGravity(binding.tvInhibition, Gravity.LEFT or Gravity.CENTER_VERTICAL)
                                .setWidth(SizeUtils.dp2px(130f))
                        }
                        binding?.tvLeading?.setOnClickListener{
                            binding.tvAngle.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvCheju.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvInhibition.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvLeading.setBackgroundColor(getCompatColor(R.color.c_f5))
                            binding.tvDelay.setBackgroundColor(getCompatColor(R.color.white))
                            CustomDialog.show(object : OnBindingView<CustomDialog?, DialogSettingItemBinding?>() {
                                override fun onBind(dialog: CustomDialog?, view: View, itemPararmBinding: DialogSettingItemBinding?) {
                                    itemPararmBinding?.tvName?.text = "前沿"

                                    itemPararmBinding?.imgAdd?.setOnClickListener {
                                        channelData.f = BigDecimal(channelData.f).add(BigDecimal("0.1")).setScale(1, RoundingMode.HALF_UP).toDouble()
                                        channelList[currentChannel] = channelData
                                        UserDataLocal.setChannelList(channelList)
                                        binding.tvLeading.text = "前沿: ${channelData.f}mm"

                                    }
                                    itemPararmBinding?.imgRemove?.setOnClickListener {
                                        if (channelData.f > 0.1) {
                                            channelData.f = BigDecimal(channelData.f).subtract(BigDecimal("0.1")).setScale(1, RoundingMode.HALF_UP).toDouble()
                                            channelList[currentChannel] = channelData
                                            UserDataLocal.setChannelList(channelList)
                                            binding.tvLeading.text = "前沿: ${channelData.f}mm"
                                        }

                                    }
                                }
                            }).setAlignBaseViewGravity(binding.tvLeading, Gravity.LEFT or Gravity.CENTER_VERTICAL)
                                .setWidth(SizeUtils.dp2px(130f))
                        }
                        binding?.tvDelay?.setOnClickListener{
                            binding.tvAngle.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvCheju.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvInhibition.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvLeading.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvDelay.setBackgroundColor(getCompatColor(R.color.c_f5))
                            CustomDialog.show(object : OnBindingView<CustomDialog?, DialogSettingItemBinding?>() {
                                override fun onBind(dialog: CustomDialog?, view: View, itemPararmBinding: DialogSettingItemBinding?) {
                                    itemPararmBinding?.tvName?.text = "延时"

                                    itemPararmBinding?.imgAdd?.setOnClickListener {
                                        channelData.lcList[channelData.selectLcIndex].delay++
                                        channelList[currentChannel] = channelData
                                        UserDataLocal.setChannelList(channelList)
                                        binding.tvDelay.text = "延时: ${channelData.lcList[channelData.selectLcIndex].delay}uS"
                                        updateLc()

                                    }
                                    itemPararmBinding?.imgRemove?.setOnClickListener {
                                        if (channelData.lcList[channelData.selectLcIndex].delay > 0) {
                                            channelData.lcList[channelData.selectLcIndex].delay--
                                            channelList[currentChannel] = channelData
                                            UserDataLocal.setChannelList(channelList)
                                            binding.tvDelay.text = "延时: ${channelData.lcList[channelData.selectLcIndex].delay}uS"
                                            updateLc()
                                        }

                                    }
                                }
                            })
                                .setAlignBaseViewGravity(binding.tvDelay, Gravity.LEFT or Gravity.CENTER_VERTICAL)
                                .setWidth(SizeUtils.dp2px(130f))
                        }

                    }
                }).setAlignBaseViewGravity(binding.btnParam, Gravity.LEFT or Gravity.CENTER_VERTICAL)
                    .setMaskColor(Color.parseColor("#4D000000"))
                    .setBaseViewMarginLeft(SizeUtils.dp2px(300f))
                    .setWidth(SizeUtils.dp2px(130f))
                    .setDialogLifecycleCallback(object : DialogLifecycleCallback<CustomDialog>(){
                        override fun onShow(dialog: CustomDialog?) {
                            super.onShow(dialog)
                            var color = UserDataLocal.colorBg
                            var selectColor = if (color == Color.WHITE) Color.BLACK else Color.WHITE
                            setShapeViews(listOf(v),selectColor)
                        }

                        override fun onDismiss(dialog: CustomDialog?) {
                            super.onDismiss(dialog)
                            var color = UserDataLocal.colorBg
                            setShapeViews(listOf(v),color)
                        }

                    })
            }
            R.id.btnSetting->{
                CustomDialog.show(object : OnBindingView<CustomDialog?, DialogSettingBinding?>() {
                    override fun onBind(dialog: CustomDialog?, view: View, binding: DialogSettingBinding?) {
                        binding?.tvDb?.text = "整机增益: ${UserDataLocal.globalDB}dB"
                        binding?.tvBgColor?.setOnClickListener {
                            binding.tvBgColor.setBackgroundColor(getCompatColor(R.color.c_f5))
                            binding.tvLineColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvBaoluoColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvRuleColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvDacColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvDb.setBackgroundColor(getCompatColor(R.color.white))
                            //更换主题颜色
                            var colorList = Utils.getBgColorList()
                            PopMenu.show(binding.tvBgColor,colorList.map { it.name })
                                .setWidth(SizeUtils.dp2px(130f))
                                .setOverlayBaseView(false)
                                .setAlignGravity(Gravity.LEFT or Gravity.CENTER_VERTICAL)
                                .setOnMenuItemClickListener { dialog, text, index ->
                                    UserDataLocal.colorBg = colorList[index].color
                                    updateBgColor()
                                    LineChartManager.updateDataColor(this@ChartActivity.binding.chartView, LineChartManager.WAVE_FROM, Utils.getFanValue(UserDataLocal.waveformBg))
                                    LineChartManager.updateDataColor(this@ChartActivity.binding.chartView, LineChartManager.BAOLUO, Utils.getFanValue(UserDataLocal.baoluoBg))
                                    LineChartManager.updateDataColor(this@ChartActivity.binding.chartView, LineChartManager.RULER, Utils.getFanValue(UserDataLocal.rulerBg))
                                    if( UserDataLocal.isOpenDAC)LineChartManager.updateDataColor(this@ChartActivity.binding.chartView, LineChartManager.DAC, Utils.getFanValue(UserDataLocal.dacBg))
                                    false
                                }
                        }
                        binding?.tvLineColor?.setOnClickListener {
                            //波形颜色
                            binding.tvBgColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvLineColor.setBackgroundColor(getCompatColor(R.color.c_f5))
                            binding.tvBaoluoColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvRuleColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvDacColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvDb.setBackgroundColor(getCompatColor(R.color.white))

                            CustomDialog.show(object : OnBindingView<CustomDialog?, DialogColorBinding>() {
                                override fun onBind(colorDialog: CustomDialog?, view: View, colorBinding: DialogColorBinding) {
                                    var colorList = Utils.getWaveformColorList()
                                    colorBinding.rv.linear()
                                        .setup {
                                            addType<ColorData>(R.layout.item_color)
                                            onClick(R.id.item){
                                               var model = getModel<ColorData>()
                                                UserDataLocal.waveformBg = Utils.getFanValue(model.color)
                                                LineChartManager.updateDataColor(this@ChartActivity.binding.chartView, LineChartManager.WAVE_FROM, Utils.getFanValue(model.color))
                                                colorDialog?.dismiss()
                                            }
                                        }.models = colorList

                                }
                            }).setAlignBaseViewGravity(binding.tvLineColor, Gravity.LEFT)
                                .setMaskColor(Color.parseColor("#4D000000"))
                                .setBaseViewMarginLeft(SizeUtils.dp2px(300f))
                                .setWidth(SizeUtils.dp2px(130f))
                        }

                        binding?.tvBaoluoColor?.setOnClickListener {
                            //包络颜色
                            binding.tvBgColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvLineColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvBaoluoColor.setBackgroundColor(getCompatColor(R.color.c_f5))
                            binding.tvRuleColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvDacColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvDb.setBackgroundColor(getCompatColor(R.color.white))
                            //更换主题颜色
                            CustomDialog.show(object : OnBindingView<CustomDialog?, DialogColorBinding>() {
                                override fun onBind(colorDialog: CustomDialog?, view: View, colorBinding: DialogColorBinding) {
                                    var colorList = Utils.getWaveformColorList()
                                    colorBinding.rv.linear()
                                        .setup {
                                            addType<ColorData>(R.layout.item_color)
                                            onClick(R.id.item){
                                                var model = getModel<ColorData>()
                                                UserDataLocal.baoluoBg = Utils.getFanValue(model.color)
                                                LineChartManager.updateDataColor(this@ChartActivity.binding.chartView, LineChartManager.BAOLUO, Utils.getFanValue(model.color))
                                                colorDialog?.dismiss()
                                            }
                                        }.models = colorList
                                }
                            }).setAlignBaseViewGravity(binding.tvBaoluoColor, Gravity.LEFT)
                                .setMaskColor(Color.parseColor("#4D000000"))
                                .setBaseViewMarginLeft(SizeUtils.dp2px(300f))
                                .setWidth(SizeUtils.dp2px(130f))
                        }

                        binding?.tvRuleColor?.setOnClickListener {
                            //包络颜色
                            binding.tvBgColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvLineColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvBaoluoColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvDacColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvRuleColor.setBackgroundColor(getCompatColor(R.color.c_f5))
                            binding.tvDb.setBackgroundColor(getCompatColor(R.color.white))
                            CustomDialog.show(object : OnBindingView<CustomDialog?, DialogColorBinding>() {
                                override fun onBind(colorDialog: CustomDialog?, view: View, colorBinding: DialogColorBinding) {
                                    var colorList = Utils.getWaveformColorList()
                                    colorBinding.rv.linear()
                                        .setup {
                                            addType<ColorData>(R.layout.item_color)
                                            onClick(R.id.item){
                                                var model = getModel<ColorData>()
                                                UserDataLocal.rulerBg = Utils.getFanValue(model.color)
                                                LineChartManager.updateDataColor(this@ChartActivity.binding.chartView, LineChartManager.RULER, Utils.getFanValue(model.color))
                                                colorDialog?.dismiss()
                                            }
                                        }.models = colorList
                                }
                            }).setAlignBaseViewGravity(binding.tvRuleColor, Gravity.LEFT)
                                .setMaskColor(Color.parseColor("#4D000000"))
                                .setBaseViewMarginLeft(SizeUtils.dp2px(300f))
                                .setWidth(SizeUtils.dp2px(130f))
                        }
                        binding?.tvDacColor?.setOnClickListener {

                            if(! UserDataLocal.isOpenDAC){
                               toast("请先打开DAC")
                               return@setOnClickListener
                            }
                            //dac颜色
                            binding.tvBgColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvLineColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvBaoluoColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvDacColor.setBackgroundColor(getCompatColor(R.color.c_f5))
                            binding.tvRuleColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvDb.setBackgroundColor(getCompatColor(R.color.white))
                            CustomDialog.show(object : OnBindingView<CustomDialog?, DialogColorBinding>() {
                                override fun onBind(colorDialog: CustomDialog?, view: View, colorBinding: DialogColorBinding) {
                                    var colorList = Utils.getWaveformColorList()
                                    colorBinding.rv.linear()
                                        .setup {
                                            addType<ColorData>(R.layout.item_color)
                                            onClick(R.id.item){
                                                var model = getModel<ColorData>()
                                                UserDataLocal.dacBg = Utils.getFanValue(model.color)
                                                LineChartManager.updateDataColor(this@ChartActivity.binding.chartView, LineChartManager.DAC, Utils.getFanValue(model.color))
                                                colorDialog?.dismiss()
                                            }
                                        }.models = colorList
                                }
                            }).setAlignBaseViewGravity(binding.tvDacColor, Gravity.LEFT)
                                .setMaskColor(Color.parseColor("#4D000000"))
                                .setBaseViewMarginLeft(SizeUtils.dp2px(300f))
                                .setWidth(SizeUtils.dp2px(130f))
                        }

                        binding?.tvDb?.setOnClickListener {
                            //全局增益
                            binding.tvBgColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvLineColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvBaoluoColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvRuleColor.setBackgroundColor(getCompatColor(R.color.white))
                            binding.tvDb.setBackgroundColor(getCompatColor(R.color.c_f5))
                            CustomDialog.show(object : OnBindingView<CustomDialog?, DialogSettingItemBinding?>() {
                                override fun onBind(dialog: CustomDialog?, view: View, itemSettingBinding: DialogSettingItemBinding?) {
                                    itemSettingBinding?.tvName?.text = "增益"
                                    itemSettingBinding?.imgAdd?.setOnClickListener {
                                        if (UserDataLocal.globalDB < 10.0F) {
                                            UserDataLocal.globalDB += 0.5F
                                            binding.tvDb.text = "增益: ${UserDataLocal.globalDB}dB"

                                            UserDataLocal.saveSendData(10, (UserDataLocal.globalDB*10).toInt().toByte())
                                            updateBuff(0)
                                        } else {
                                            toast("增益已达到最大值10DB")
                                        }
                                    }
                                    itemSettingBinding?.imgRemove?.setOnClickListener {
                                        if (UserDataLocal.globalDB >= 0.5F) {
                                            UserDataLocal.globalDB -= 0.5F
                                            binding.tvDb.text = "增益: ${UserDataLocal.globalDB}dB"
                                            UserDataLocal.saveSendData(10, (UserDataLocal.globalDB*10).toInt().toByte())
                                            updateBuff(0)
                                        }else{
                                            toast("已经无法再减少增益了")
                                        }
                                    }
                                }
                            }).setAlignBaseViewGravity(binding.tvDb, Gravity.LEFT or Gravity.CENTER_VERTICAL)
                                .setWidth(SizeUtils.dp2px(130f))
                                .setMaskColor(Color.parseColor("#4D000000"))
                        }

                    }
                }).setAlignBaseViewGravity(binding.btnSetting, Gravity.LEFT or Gravity.TOP)
                    .setMaskColor(Color.parseColor("#4D000000"))
                    .setBaseViewMarginLeft(SizeUtils.dp2px(300f))
                    .setWidth(SizeUtils.dp2px(130f))
                    .setDialogLifecycleCallback(object : DialogLifecycleCallback<CustomDialog>(){
                        override fun onShow(dialog: CustomDialog?) {
                            super.onShow(dialog)
                            var color = UserDataLocal.colorBg
                            var selectColor = if (color == Color.WHITE) Color.BLACK else Color.WHITE
                            setShapeViews(listOf(v),selectColor)
                        }

                        override fun onDismiss(dialog: CustomDialog?) {
                            super.onDismiss(dialog)
                            var color = UserDataLocal.colorBg
                            setShapeViews(listOf(v),color)
                        }

                    })

            }
            R.id.btnDAC->{
                if (! UserDataLocal.isOpenDAC){
                    toast("请先打开DAC模式")
                    return
                }
                PopMenu.show(v, arrayOf("添加点","删除点","保存曲线","删除曲线","恢复默认"))
                    .setWidth(SizeUtils.dp2px(130f))
                    .setOverlayBaseView(false)
                    .setAlignGravity(Gravity.LEFT or Gravity.CENTER_VERTICAL)
                    .setOnMenuItemClickListener { dialog, text, index ->
                        when(index){
                            0->{ //添加点
                                if (LineChartManager.rule.first != 0 && LineChartManager.rule.second != 0){
                                    UserDataLocal.saveDacPoint = true
                                }else{
                                    toast("测量尺寸未测量完成，无法添加点")
                                }
                            }
                            1->{  //删除点
                                //删除 dacPointList 最后一项
                                if (dacPointList.isNotEmpty()){
                                    dacPointList.removeLast()
                                }
                                LineChartManager.updateDacLine(binding.chartView,dacPointList)
                            }
                            2->{  //保存曲线
                                var channelList = UserDataLocal.getChannelList()
                                channelList[currentChannel].dacPointList = dacPointList
                                UserDataLocal.setChannelList(channelList)
                                toast("已保存曲线")
                            }
                            3->{  //删除曲线
                                var channelList = UserDataLocal.getChannelList()
                                dacPointList = mutableListOf()
                                channelList[currentChannel].dacPointList = dacPointList
                                UserDataLocal.setChannelList(channelList)
                                LineChartManager.updateDacLine(binding.chartView,dacPointList)
                                toast("已清空曲线")
                            }
                            4->{  //恢复默认
                                var channelList = UserDataLocal.getChannelList()
                                channelList[currentChannel].dacPointList =  channelList[currentChannel].dacDefaultPointList
                                UserDataLocal.setChannelList(channelList)
                                toast("已恢复默认")
                            }
                        }
                        false
                    }
                    .setDialogLifecycleCallback(object : DialogLifecycleCallback<PopMenu>(){
                        override fun onShow(dialog: PopMenu?) {
                            super.onShow(dialog)
                            var color = UserDataLocal.colorBg
                            var selectColor = if (color == Color.WHITE) Color.BLACK else Color.WHITE
                            setShapeViews(listOf(v),selectColor)
                        }

                        override fun onDismiss(dialog: PopMenu?) {
                            super.onDismiss(dialog)
                            var color = UserDataLocal.colorBg
                            setShapeViews(listOf(v),color)
                        }

                    })
            }
        }
    }

    private fun setBtnPressColor(view:Any){
        var color = UserDataLocal.colorBg
        var selectColor = if (color == Color.WHITE) Color.BLACK else Color.WHITE
        setShapeViews(listOf(
            binding.btnAddBuff,
            binding.btnAddBuff2,
            binding.btnReduceBuff,
            binding.btnReduceBuff2,
            binding.btnParam,
            binding.btnSetting,
            binding.btnChannel,
            binding.btnChannel2,
            binding.btnDAC
        ),color)
        setShapeViews(listOf(view),selectColor)
    }

    /**
     * 设置对话框修改参数
     * 更改量程角度
     * */
    private fun updateChannelAngle(newKValue: Double, textView:TextView) {
        var channelList = UserDataLocal.getChannelList()
        var channelData = channelList[currentChannel]

        // 使用 BigDecimal 进行精确计算
        val currentKValue = BigDecimal(channelData.kValue)
        val newKValueBD = BigDecimal(newKValue)
        var updatedKValue = currentKValue.add(newKValueBD).setScale(2, RoundingMode.HALF_UP).toDouble()
        if (updatedKValue < 0) {
            updatedKValue = 0.0
        }
        channelData.kValue  = updatedKValue
        textView.text = "角度: K${BigDecimal(channelData.kValue).setScale(2, RoundingMode.HALF_UP)}"
        binding.tvAngle.text = "角度: K${BigDecimal(channelData.kValue).setScale(2, RoundingMode.HALF_UP)}"
        binding.tvAngle2.text = "角度: K${BigDecimal(channelData.kValue).setScale(2, RoundingMode.HALF_UP)}"

        val tan = kotlin.math.atan(channelData.kValue)
        val bigDecimal = BigDecimal(tan).setScale(3, RoundingMode.DOWN)
        channelData.sinb = BigDecimal(kotlin.math.sin(bigDecimal.toDouble())).setScale(3, RoundingMode.DOWN).toDouble()
        channelData.logb = BigDecimal(kotlin.math.cos(bigDecimal.toDouble())).setScale(3, RoundingMode.DOWN).toDouble()
        channelList[currentChannel] = channelData
        UserDataLocal.setChannelList(channelList)
    }

    private fun updateBgColor(){
        val color = UserDataLocal.colorBg
        LineChartManager.setGuidelines(binding.chartView)
        setShapeViews(listOf(
            binding.btnAddBuff,
            binding.btnReduceBuff,
            binding.btnChannel,
            binding.btnParam,
            binding.btnDAC,
            binding.btnSetting,
            binding.btnAddBuff2,
            binding.btnReduceBuff2,
            binding.btnBack2,
            binding.btnChannel2,
            binding.tvBuff2,
            binding.tvDate,
            binding.tvAngle2,
            binding.tvLc2,
            binding.tvInhibition2,
            binding.tvHorizontal2,
            binding.tvDepth2,
            binding.tvAmplitude2,
            binding.tvEquivalent2,
            binding.tvBuff,
            binding.tvAngle,
            binding.tvLc,
            binding.tvInhibition,
            binding.tvHorizontal,
            binding.tvDepth,
            binding.tvSound,
            binding.tvAmplitude,
            binding.tvEquivalent,
            binding.tvStepping,
            binding.tvMode,
            binding.imgStepping,
            binding.tvPower
        ),color)
        when(color){
            Color.WHITE->{
                binding.layVer.background = ContextCompat.getDrawable(this, R.color.white)
                binding.layIcon.background = ContextCompat.getDrawable(this, R.color.white)
                binding.line2.background = ContextCompat.getDrawable(this, R.color.black)
                binding.layAll.background = ContextCompat.getDrawable(this, R.color.white)

                if(!isOpenCamera) binding.imgCamera.setImageResource(R.mipmap.ic_camera_black)
                if(!isOpenSave) binding.imgSave.setImageResource(R.mipmap.ic_save_black)
                if(!isPause) binding.imgXing.setColorFilter(Color.BLACK, PorterDuff.Mode.SRC_IN)
                binding.imgBaoLuo.setImageResource(if (isOpenBaoluo) R.mipmap.ic_baoluo_black else R.mipmap.ic_baoluo_black_error)
                binding.imgDac.setImageResource(if ( UserDataLocal.isOpenDAC) R.mipmap.ic_dac_black else R.mipmap.ic_dac_black_error)
            }
            Color.BLACK->{
                binding.layVer.background = ContextCompat.getDrawable(this, R.color.black)
                binding.layIcon.background = ContextCompat.getDrawable(this, R.color.black)
                binding.line2.background = ContextCompat.getDrawable(this, R.color.white)
                binding.layAll.background = ContextCompat.getDrawable(this, R.color.black)

                if(!isOpenCamera) binding.imgCamera.setImageResource(R.mipmap.ic_camera_white)
                if(!isOpenSave) binding.imgSave.setImageResource(R.mipmap.ic_save_white)
                if(!isPause) binding.imgXing.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN)
                binding.imgBaoLuo.setImageResource(if (isOpenBaoluo) R.mipmap.ic_baoluo_white else R.mipmap.ic_baoluo_white_error)
                binding.imgDac.setImageResource(if ( UserDataLocal.isOpenDAC) R.mipmap.ic_dac_white else R.mipmap.ic_dac_white_error)
            }
        }

    }

    private fun setShapeViews(shapeBtns: List<Any>,color:Int) {
        var textColor = if (color == Color.WHITE) Color.BLACK else Color.WHITE
        var solidColor = color

        shapeBtns.forEach { shapeBtn ->
            when (shapeBtn) {
                is ShapeButton -> {
                    shapeBtn.setTextColor(textColor)
                    shapeBtn.shapeDrawableBuilder
                        .setSolidColor(solidColor)
                        .setStrokeColor(textColor)
                        .intoBackground()

                }
                is ShapeImageView -> {
                    shapeBtn.setColorFilter(textColor, PorterDuff.Mode.SRC_IN)
                    shapeBtn.shapeDrawableBuilder
                        .setSolidColor(solidColor)
                        .setStrokeColor(textColor)
                        .intoBackground()
                }
                is TextView -> {
                    shapeBtn.setTextColor(textColor)
                }
                is ImageView -> {
                    shapeBtn.setColorFilter(textColor, PorterDuff.Mode.SRC_IN)
                }
            }
        }
    }


    private fun showChannelMenuDialog(v:View){
        var alignGravity = if(v.id == R.id.btnChannel) Gravity.LEFT or Gravity.CENTER_VERTICAL else Gravity.CENTER_HORIZONTAL or Gravity.BOTTOM

        val namesList: List<CharSequence> =  UserDataLocal.getChannelList().map { it.name }

        CustomDialog.show(object : OnBindingView<CustomDialog?, DialogColorBinding>() {
            override fun onBind(colorDialog: CustomDialog?, view: View, colorBinding: DialogColorBinding) {

                colorBinding.rv.linear()
                    .setup {
                        addType<String>(R.layout.item_channel)
                        onClick(R.id.item){
                            currentChannel = modelPosition

                            dacPointList = UserDataLocal.getChannelList()[currentChannel].dacPointList
                            updateLc()
                            this@ChartActivity.binding.btnChannel.text = namesList[currentChannel]
                            this@ChartActivity.binding.btnChannel2.text = namesList[currentChannel]
                            this@ChartActivity.binding.tvAngle.text = "角度: K${BigDecimal(UserDataLocal.getChannelList()[currentChannel].kValue).setScale(2, RoundingMode.HALF_UP)}"
                            this@ChartActivity.binding.tvAngle2.text = "角度: K${BigDecimal(UserDataLocal.getChannelList()[currentChannel].kValue).setScale(2, RoundingMode.HALF_UP)}"
                            colorDialog?.dismiss()
                        }
                    }.models = namesList

            }
        }).setAlignBaseViewGravity(v, alignGravity)
            .setMaskColor(Color.parseColor("#4D000000"))
            .setBaseViewMarginLeft(SizeUtils.dp2px(300f))
            .setWidth(SizeUtils.dp2px(130f))
            .setDialogLifecycleCallback(object : DialogLifecycleCallback<CustomDialog>(){
                override fun onShow(dialog: CustomDialog?) {
                    super.onShow(dialog)
                    var color = UserDataLocal.colorBg
                    var selectColor = if (color == Color.WHITE) Color.BLACK else Color.WHITE
                    setShapeViews(listOf(v),selectColor)
                }

                override fun onDismiss(dialog: CustomDialog?) {
                    super.onDismiss(dialog)
                    var color = UserDataLocal.colorBg
                    setShapeViews(listOf(v),color)
                }

            })
    }

    /**
     * 更新量程信息，发送信息
     * */
    fun updateLc(){
        var channelList = UserDataLocal.getChannelList()
        var channelData = channelList[currentChannel]

        //更新dac
        LogUtils.i("更新dac",dacPointList)
        for (point in dacPointList){
            var newXSC = point.lc.toDouble() / channelData.lcList[channelData.selectLcIndex].value
            point.x = (point.x * newXSC).toFloat()
            point.lc = channelData.lcList[channelData.selectLcIndex].value
        }

        if (dacPointList.isNotEmpty()){
            for (point in dacPointList){
                var newY = point.y * Math.pow(10.0, ((UserDataLocal.globalBuff - point.db).toDouble()/200))
                point.db = UserDataLocal.globalBuff
                point.y = newY.toFloat()
            }
        }else{
            binding.tvEquivalent.text = "当量: 00dB"
            binding.tvEquivalent2.text = "当量: 00dB"
        }
        LineChartManager.updateDacLine(binding.chartView, dacPointList)


        binding.tvLc.text = "测距:${channelData.lcList[channelData.selectLcIndex].name}"
        binding.tvLc2.text = "测距:${channelData.lcList[channelData.selectLcIndex].name}"
        binding.tvAngle.text = "角度: K${BigDecimal(channelData.kValue).setScale(1, RoundingMode.HALF_UP)}"
        binding.tvAngle2.text = "角度: K${BigDecimal(channelData.kValue).setScale(1, RoundingMode.HALF_UP)}"

        //获取延时
        var delay =  channelData.lcList[channelData.selectLcIndex].delay

        //将延时转换成16进制字符串
        var delayHex = delay.toString(16)

        val (highByteHex, lowByteHex) = Utils.splitIntoHexBytes(channelData.lcList[channelData.selectLcIndex].control)
        UserDataLocal.saveSendData(4, lowByteHex.toInt(16).toByte())
        UserDataLocal.saveSendData(5, highByteHex.toInt(16).toByte())
        UserDataLocal.saveSendData(6, delayHex.toInt(16).toByte())

        blueViewModel.sendData(UserDataLocal.sendData)
    }

    /**
     * 增加减少增益
     * @param value 增加或减少的值
     * */
   private fun updateBuff(value: Int){
       //todo (800- value)/10  保留一位小数 单位db
        UserDataLocal.globalBuff += value
        if (UserDataLocal.globalBuff < 0){
            UserDataLocal.globalBuff = 0
        }
        if (UserDataLocal.globalBuff > 800){
            UserDataLocal.globalBuff = 800
        }
        //更改dac 曲线
        if (dacPointList.isNotEmpty()){
            for (point in dacPointList){
                var newY = point.y * Math.pow(10.0, ((UserDataLocal.globalBuff - point.db).toDouble()/200))
                point.db = UserDataLocal.globalBuff
                point.y = newY.toFloat()
            }
            LineChartManager.updateDacLine(binding.chartView, dacPointList)
//            if ( UserDataLocal.isOpenDAC) LineChartManager.updateDacLine(binding.chartView, dacPointList)
        }
        binding.tvBuff.text = Utils.getBuffStr()
        binding.tvBuff2.text = Utils.getBuffStr()
        //10月11日改动 将全局增益拆分出来单独发送
        val (highByteHex, lowByteHex) = Utils.splitIntoHexBytes(UserDataLocal.globalBuff)
        UserDataLocal.saveSendData(2, lowByteHex.toInt(16).toByte())
        UserDataLocal.saveSendData(3, highByteHex.toInt(16).toByte())
        blueViewModel.sendData(UserDataLocal.sendData)
    }


    //更新折线图
    private fun updateChart(value: ByteArray) {
//        LogUtils.eTag("ByteArray", "收到数据：$value")
        var hexStr = StringUtils.toHex(value, ",")
        var hexArray = hexStr.split(",")
//        LogUtils.eTag("hexArray", "hexStr：$hexStr")

        var powerValue = Utils.combineHexBytesToInt(hexArray[509],hexArray[510])
        var power= Utils.getPower(powerValue)
        binding.tvPower.text = "电量:${power}%"

        //抑制值
        //默认为百分之0。此功能默认增加为1←此功能用于筛除数值低于此数值的波形。如抑制为50则实时刷新显示时 低于254*50%=127.5 的值的项显示为0
        var inhibition = 254 * UserDataLocal.globalInhibition / 100

        val entries = hexArray.take(500).mapIndexed { index, hexValue ->
            if (inhibition<hexValue.toInt(16).toFloat()){
                Entry(index.toFloat(), hexValue.toInt(16).toFloat())
            }else{
                Entry(index.toFloat(), 0f)
            }

        }.toMutableList()

        //判断是否选择了测量尺
        if (LineChartManager.rule.first != -1 && LineChartManager.rule.second != -1){
            var ruleList = entries.slice(LineChartManager.rule.first..LineChartManager.rule.second)
            // 获取 ruleList 中的最大值
            val maxElement = ruleList.maxBy { it.y }
//            LogUtils.eTag("测量尺",ruleList.toString())
//            LogUtils.eTag("maxElement",maxElement.toString())
//            LogUtils.eTag("RULEy",LineChartManager.ruleY)

            var channelList = UserDataLocal.getChannelList()
            var channelData = channelList[currentChannel]

            if (UserDataLocal.saveDacPoint){
                //取出当前通道下的dac点位列表

                var dacPointData = DacPointData(maxElement.x, maxElement.y, channelData.lcList[channelData.selectLcIndex].value,UserDataLocal.globalBuff)
                //判断列表中是否含有当前x点，如果有，则覆盖，没有则添加
                var index = dacPointList.indexOfFirst { it.x == dacPointData.x }
                var strInfo = "x=${maxElement.x}   y=${maxElement.y}  lc=${channelData.lcList[channelData.selectLcIndex].value}  db=${UserDataLocal.globalBuff}"
                if (index != -1){
                    dacPointList[index] = dacPointData
                    toast("添加点位"+strInfo)
                    LogUtils.e("DAC","添加点位"+strInfo)
                }else{
                    dacPointList.add(dacPointData)
                    toast("更新点位"+strInfo)
                    LogUtils.e("DAC","更新点位"+strInfo)
                }
                UserDataLocal.saveDacPoint = false
                LineChartManager.updateDacLine(binding.chartView,dacPointList)
            }

            //计算当量
//            var dacEntryList = LineChartManager.getDacLine(binding.chartView)
            var dacEntryList = LineChartManager.dacList
//            LogUtils.e("dacEntryList",dacEntryList.toString())
            //判断当前 maxElement的x轴数据是否在dacEntry中，如果在，则取dacEntry中该x轴的数据，如果不在，则取出距离x值最近两个点的位置
            var dacIndex = dacEntryList.indexOfFirst { it.x == maxElement.x }


            if (dacIndex != -1){
                //取dacEntry中该x轴的数据
                var dacY = dacEntryList[dacIndex].y
//                    //计算当量
                var dbString = Utils.getDBValue(maxElement.y.toDouble(),dacY.toDouble())
                if (maxElement.y > LineChartManager.ruleY) {
                    binding.tvEquivalent.text = "当量: ${dbString}dB"
                    binding.tvEquivalent2.text = "当量: ${dbString}dB"
                }else{
                    binding.tvEquivalent.text = "当量: 000dB"
                    binding.tvEquivalent2.text = "当量: 000dB"
                }
            }else{
                //取出dacEntry中的在maxElement.x 之间两个点
                var dacIndex1 = dacEntryList.indexOfFirst { it.x > maxElement.x }
                var dacIndex2 = dacEntryList.indexOfFirst { it.x < maxElement.x }
                if (dacIndex1 != -1 && dacIndex2 != -1){
                    var point1 = dacEntryList[dacIndex1]
                    var point2 = dacEntryList[dacIndex2]
                    //计算斜率
                    var slope = (point1.y - point2.y) / (point1.x - point2.x)
//                    LogUtils.eTag("斜率","point1-y${point1.y} point2-y${point2.y} point1-x${point1.x} point2-x${point2.x} 斜率${slope}")
                    var dacY = point2.y + slope * (maxElement.x - point2.x)
                    var dbString = Utils.getDBValue(maxElement.y.toDouble(),dacY.toDouble())
                    if (maxElement.y > LineChartManager.ruleY) {
                        binding.tvEquivalent.text = "当量: ${dbString}dB"
                        binding.tvEquivalent2.text = "当量: ${dbString}dB"
                    }else{
                        binding.tvEquivalent.text = "当量: 000dB"
                        binding.tvEquivalent2.text = "当量: 000dB"
                    }

                }
            }


            //更新测量点 addRulePoint
            var pointList = mutableListOf(maxElement, Entry(maxElement.x+1, maxElement.y))
            LineChartManager.addRulePoint(binding.chartView,pointList)


//            LogUtils.eTag("maxElement",maxElement.toString())
            if (maxElement.y > LineChartManager.ruleY) {
                var horizontal = Utils.mathHorizontal(maxElement.x, channelData.lcList[channelData.selectLcIndex].value,
                    channelData.sinb, channelData.f)
                var depth = Utils.mathDepth(maxElement.x, channelData.lcList[channelData.selectLcIndex].value,channelData.logb)
                var sound = Utils.mathSound(maxElement.x, channelData.lcList[channelData.selectLcIndex].value)
                var amplitude = Utils.mathAmplitude(maxElement.y)
                binding.tvHorizontal.text = "水平:${Utils.toZeroString(horizontal)}mm"
                binding.tvHorizontal2.text = "水平:${Utils.toZeroString(horizontal)}mm"
                binding.tvDepth.text = "深度:${Utils.toZeroString(depth)}mm"
                binding.tvDepth2.text = "深度:${Utils.toZeroString(depth)}mm"
                binding.tvSound.text = "声程:${Utils.toZeroString(sound)}mm"
                binding.tvAmplitude.text = "波幅:${(amplitude*100).toInt()}%"
                binding.tvAmplitude2.text = "波幅:${(amplitude*100).toInt()}%"
            }else{
                binding.tvHorizontal.text = "水平:000mm"
                binding.tvHorizontal2.text = "水平:000mm"
                binding.tvDepth.text = "深度:000mm"
                binding.tvDepth2.text = "深度:000mm"
                binding.tvSound.text = "声程:000mm"
                binding.tvAmplitude.text = "波幅:0%"
                binding.tvAmplitude2.text = "波幅:0%"
            }

        }

        if (isOpenBaoluo){
            var baoluoHexStr = StringUtils.toHex(value, ",")
            var baoluoHexArray = baoluoHexStr.split(",")
            val baoluoEntries = baoluoHexArray.take(500).mapIndexed { index, hexValue ->
                baolupArray[index] = if (hexValue.toInt(16).toFloat()>= baolupArray[index]){
                    hexValue.toInt(16).toFloat()
                }else{
                    baolupArray[index]
                }
                Entry(index.toFloat(), baolupArray[index])
            }.toMutableList()
            LineChartManager.addBaoluo(binding.chartView, baoluoEntries)
        }else{
            LineChartManager.addBaoluo(binding.chartView, mutableListOf())
        }
        LineChartManager.addWaveform(binding.chartView, entries)
    }

    //    ======摄像头==========
    fun updateCameraModel(isOpen :Boolean){
        binding.layTvHor.visibility = if (isOpen) View.VISIBLE else View.GONE
        binding.layVer.visibility = if (isOpen) View.GONE else View.VISIBLE
        binding.cameraView.visibility = if (isOpen) View.VISIBLE else View.GONE
        if (isOpen){
            binding.imgCamera.setImageResource(R.mipmap.ic_camera_red)
        }else if (UserDataLocal.colorBg == Color.WHITE){
            binding.imgCamera.setImageResource(R.mipmap.ic_camera_black)
        }else if (UserDataLocal.colorBg == Color.BLACK){
            binding.imgCamera.setImageResource(R.mipmap.ic_camera_white)
        }
        if (isOpen){
            resumeCamera()
        }else{
            pauseCamera()
        }
    }

    private fun bindCamera() {
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener({
            val cameraProvider = cameraProviderFuture.get()

            //创建预览
            val preview = Preview.Builder().build()
            //绑定预览View
            preview.setSurfaceProvider(binding.cameraView.surfaceProvider)

            //选择前置或者后置摄像头
            // CameraSelector.LENS_FACING_FRONT --前置
            // CameraSelector.LENS_FACING_BACK --后置
            val cameraSelector = CameraSelector.Builder()
                .requireLensFacing(CameraSelector.LENS_FACING_BACK)
                .build()

            //拍照
            imageCapture = ImageCapture.Builder()
                //设置旋转
                .setTargetRotation(binding.cameraView.display.rotation)
                //设置拍照模式
                // ImageCaptureCAPTURE_MODE_MINIMIZE_LATENCY --缩短拍摄延迟时间
                // ImageCaptureCAPTURE_MODE_MAXIMIZE_QUALITY --优化照片质量
                .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
                .build()

            cameraProvider.unbindAll()
            cameraProvider.bindToLifecycle(cameraLifecycle, cameraSelector, imageCapture, preview)
        }, ContextCompat.getMainExecutor(this))
    }

    //    ======屏幕录制==========
    private fun updateScreenRecordingModel(isOpen :Boolean){
        binding.tvTime.visibility = if (isOpen && isOpenCamera) View.VISIBLE else View.GONE
        binding.tvTime2.visibility = if (isOpen && !isOpenCamera) View.VISIBLE else View.GONE
        if (isOpen){
            binding.imgSave.setImageResource(R.mipmap.ic_save_red)
        }else if (UserDataLocal.colorBg == Color.WHITE){
            binding.imgSave.setImageResource(R.mipmap.ic_save_black)
        }else if (UserDataLocal.colorBg == Color.BLACK){
            binding.imgSave.setImageResource(R.mipmap.ic_save_white)
        }
        if (isOpen){
            mTimerJob = lifecycleScope.launch {
                var time = 0
                while (this.isActive) {
                    time++
                    kotlinx.coroutines.delay(1000)
                    binding.tvTime.text = Utils.formatDuration(time)
                    binding.tvTime2.text = Utils.formatDuration(time)
                }
            }
            startRecord(binding.layAll)
        }else{
            binding.tvTime.text = Utils.formatDuration(0)
            binding.tvTime2.text = Utils.formatDuration(0)
            stopRecord()
        }
    }


    private fun startRecord(view: View){
        if (viewRecord.isStartRecord) {
            toast("正在录制中")
            return
        }
        initRecord(view)
        val outputFile = File(externalCacheDir, "record_${System.currentTimeMillis()}.mp4")
        mLastRecordFile = outputFile
        // 先check一下，最后对比下参数
        val width = view.width
        val height = view.height
        LogUtils.i("startRecord(): View: width=$width, height=$height, outputFile: ${outputFile.absolutePath}")
        mStartTime = System.currentTimeMillis()
        viewRecord.startRecord(outputFile.absolutePath, object : RecordController.Listener {
            override fun onStatusChange(status: RecordController.Status?) {
                LogUtils.i( "onStatusChange() called with: status = $status")
            }
        }, object : EncoderErrorCallback {
            override fun onCodecError(type: String, e: MediaCodec.CodecException) {
                LogUtils.i("onCodecError() called with: type = $type", e)
            }
        })
    }
    private fun initRecord(view: View){
        val width = view.width
        val height = view.height
        val maxResolution = Math.min(width, height)
        viewRecord.init(
            window = window,
            view = view,
            width = maxResolution,
            fps = 60,
            videoBitRate = 8_000_000,
            iFrameInterval = 1,
            audioBitRate = 192_000,
            audioSampleRate = 44100,
            isStereo = true,
        )
    }
    private fun stopRecord(){
        // 录制时长
        val duration = System.currentTimeMillis() - mStartTime
        // 输出转换成秒毫秒
        val durationStr = "${duration / 1000}.${duration % 1000}"
        //mRecordEncoder.stop()
        viewRecord.stopRecord()
        mTimerJob?.cancel()
        mTimerJob = null
        LogUtils.i( "stopRecord() duration=${durationStr}秒, RecordFile: ${mLastRecordFile?.absolutePath}")
        openSaveDialog(mLastRecordFile)
    }
    private fun openSaveDialog(file: File?){
        CustomDialog.show(object : OnBindingView<CustomDialog?, DialogFileExplorerBinding?>() {
            override fun onBind(dialog: CustomDialog?, view: View, binding: DialogFileExplorerBinding?) {
                binding?.edName?.setText(file?.name)
                binding?.edPath?.text = UserDataLocal.savePath
                binding?.edPath?.setOnClickListener {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                        if (Environment.isExternalStorageManager()) {
                            val config = ExplorerConfig(this@ChartActivity).apply {
                                rootDir = Environment.getExternalStorageDirectory()
                                isLoadAsync = false
                                explorerMode = ExplorerMode.DIRECTORY
                                setOnFilePickedListener {
                                    UserDataLocal.savePath = it.path
                                    binding.edPath.text = it.path
                                }
                            }
                            val picker = FilePicker(this@ChartActivity)
                            picker.setExplorerConfig(config)
                            picker.show()
                        } else {
                            val intent: Intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
                            intent.setData(Uri.parse("package:" + applicationContext.packageName))
                            startActivity(intent)
                        }
                    }else{
                        val config = ExplorerConfig(this@ChartActivity).apply {
                            rootDir = Environment.getExternalStorageDirectory()
                            isLoadAsync = false
                            explorerMode = ExplorerMode.DIRECTORY
                            setOnFilePickedListener {
                                UserDataLocal.savePath = it.path
                                binding.edPath.text = it.path
                            }
                        }
                        val picker = FilePicker(this@ChartActivity)
                        picker.setExplorerConfig(config)
                        picker.show()
                    }
                }
                binding?.btnSure?.setOnClickListener {
                    val name = binding.edName.text.toString()
                    val path = binding.edPath.text.toString()
                    if(!FileUtils.isFileExists(file)){
                        toast("文件不存在")
                    }else if(com.blankj.utilcode.util.StringUtils.isEmpty(name)){
                        toast("请输入文件名")
                    }else if(!FileUtils.isDir(path)){
                        toast("请选择正确的文件夹")
                    }else{
                        var isRename = FileUtils.rename(file, name)
                        if (!isRename){ toast("重命名失败")}
                        var isRenameTo:Boolean = FileUtils.move(file, File("${path}/${file?.name}"))
                        toast(if (isRenameTo) "保存文件成功" else "文件保存失败")
                        dialog?.dismiss()
                    }

                }
                binding?.btnCancel?.setOnClickListener {
                    dialog?.dismiss()
                }
            }
        }).setWidth(SizeUtils.dp2px(600f)).setCancelable(false)

    }



    fun resumeCamera() {
        cameraLifecycle.cameraOnStart()
    }

    fun pauseCamera() {
        cameraLifecycle.cameraOnStop()
    }


    override fun onStart() {
        super.onStart()
        cameraLifecycle.cameraOnStart()
    }

    override fun onResume() {
        super.onResume()
        cameraLifecycle.cameraOnResume()
    }

    override fun onPause() {
        super.onPause()
        cameraLifecycle.cameraOnPause()
    }

    override fun onStop() {
        super.onStop()
        cameraLifecycle.cameraOnStop()
    }



    override fun onDestroy() {
        blueViewModel.stopNotify(device)
        blueViewModel.cleanup()
        super.onDestroy()
        cameraLifecycle.cameraOnDestroyed()
    }

}